package com.relytosoft.mizar.analyze.structure.services.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.relytosoft.dubhe.common.core.base.page.PageQuery;
import com.relytosoft.dubhe.common.core.exception.ServiceException;
import com.relytosoft.dubhe.common.core.object.ResponseResult;
import com.relytosoft.dubhe.common.core.utils.BeanCopyUtils;
import com.relytosoft.dubhe.common.redis.utils.RedisUtil;
import com.relytosoft.mizar.analyze.base.entity.pojo.dto.AyDispositionPlanDto;
import com.relytosoft.mizar.analyze.base.entity.pojo.dto.AyPlanTemplateDto;
import com.relytosoft.mizar.analyze.base.enums.ControlStatusEnum;
import com.relytosoft.mizar.analyze.common.feign.SystemFeignService;
import com.relytosoft.mizar.analyze.structure.api.entity.AyStructureDisposition;
import com.relytosoft.mizar.analyze.structure.api.pojo.dto.AyStructureDispositionDto;
import com.relytosoft.mizar.analyze.structure.api.pojo.dto.AyTaskIdDto;
import com.relytosoft.mizar.analyze.structure.api.pojo.query.AyStructureDispositionQuery;
import com.relytosoft.mizar.analyze.structure.api.pojo.vo.AyStructureDispositionVo;
import com.relytosoft.mizar.analyze.structure.services.mapper.AyStructureDispositionMapper;
import com.relytosoft.mizar.analyze.structure.services.service.AyStructureDispositionService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

import static com.relytosoft.mizar.analyze.base.constant.AyCacheConstants.CONTROL_STRUCTURE_CONDITION;
import static com.relytosoft.mizar.analyze.base.constant.ControlConstants.*;


/**
 * @Author: zyc
 * @version: v1.0
 * @description: com.relytosoft.mizar.analyze.structure.services.service.impl
 * @Date: 2022/5/18 15:15
 */
@Service
public class AyStructureDispositionServiceImpl extends ServiceImpl<AyStructureDispositionMapper, AyStructureDisposition> implements AyStructureDispositionService {

    @Resource
    private AyStructureDispositionMapper ayStructureDispositionMapper;

    @Resource
    private SystemFeignService systemFeignService;

    @Override
    public IPage<AyStructureDispositionVo> selectAyStructureDispositionPageList(PageQuery pageQuery, AyStructureDispositionQuery ayStructureDispositionQuery) {
        if (StrUtil.isBlank(pageQuery.getOrderByColumn())) {
            pageQuery.setOrderByColumn("id");
            pageQuery.setIsAsc("desc");
        }
        return ayStructureDispositionMapper.selectPageDispositionTaskList(pageQuery.build(), ayStructureDispositionQuery);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean insertAyStructureDisposition(AyStructureDispositionDto ayStructureDispositionDto) {
        AyStructureDisposition ayStructureDisposition = new AyStructureDisposition();
        if ((STRUCTURE_DISPOSITION_TYPE_TEST == ayStructureDispositionDto.getDispositionType() && null != ayStructureDispositionDto.getDispositionText())
                || (STRUCTURE_DISPOSITION_TYPE_IMAGE == ayStructureDispositionDto.getDispositionType() && null != ayStructureDispositionDto.getDispositionImage())
                || (STRUCTURE_DISPOSITION_VEHICLE_TYPE_GROUP == ayStructureDispositionDto.getDispositionType() && (null != ayStructureDispositionDto.getVehicleGroup()))
        ) {
            BeanCopyUtils.copy(ayStructureDispositionDto, ayStructureDisposition);
            ayStructureDisposition.setStatus(0);
            ayStructureDisposition.setDefenseStatus(0);
            ayStructureDisposition.setDispositionId(UUID.randomUUID().toString());
            ayStructureDisposition.setBeginTime(LocalDateTime.now());
            boolean save = this.save(ayStructureDisposition);
            AyDispositionPlanDto planDto = new AyDispositionPlanDto();
            if (save) {
                BeanCopyUtils.copy(ayStructureDisposition, planDto);
                String[] str = ayStructureDispositionDto.getDispositionRangeDevice().split(",");
                sendRedis(str, planDto);
                return true;
            }
            return false;
        }
        throw new ServiceException("不符合条件的布控");

    }

    @Override
    public AyStructureDisposition getAyStructureDispositionById(Integer dispositionId) {
        AyStructureDisposition ayStructureDisposition = getById(dispositionId);
        if (null != ayStructureDisposition) {
            return ayStructureDisposition;
        }
        throw new ServiceException("不存在的结构化布控任务");
    }

    @Override
    public boolean updateAyStructureDisposition(AyStructureDispositionDto ayStructureDispositionDto) {
        //1. 判断当前布控任务状态
        AyStructureDisposition disposition = this.getById(ayStructureDispositionDto.getDispositionId());
        //当布控状态为未开始或已结束并且处于撤防状态
        if (ControlStatusEnum.RUNING.getValue() != disposition.getStatus() && ControlStatusEnum.NOT_STARTED.getValue() == disposition.getDefenseStatus()) {
            //更新本库数据信息
            AyStructureDisposition ayStructureDisposition = new AyStructureDisposition();
            BeanCopyUtils.copy(ayStructureDispositionDto, ayStructureDisposition);
            boolean update = this.updateById(ayStructureDisposition);
            AyDispositionPlanDto planDto = new AyDispositionPlanDto();
            if (ayStructureDispositionDto.getPlanTemplateId() != null) {
                //3. 修改布控计划信息
                AyDispositionPlanDto dispositionPlanDto = updateAyDispositionPlan(ayStructureDisposition);
                BeanCopyUtils.copy(dispositionPlanDto, planDto);
            }
            planDto.setDispositionType(disposition.getDispositionType());
            planDto.setStatus(disposition.getStatus());
            planDto.setDefenseStatus(disposition.getDefenseStatus());
            String[] str = disposition.getDispositionRangeDevice().split(",");
            sendRedis(str, planDto);
            return update;
        }
        throw new ServiceException("布控任务所处状态不能修改");
    }

    @Override
    public boolean deleteAyStructureDisposition(List<Integer> dispositionIds) {
        List<AyStructureDisposition> list = this.listByIds(dispositionIds);
        //1. 判断是否为已停止和撤防状态
        Set<Integer> set = list.stream().filter(item -> {
            if (item.getStatus() != 1 && item.getDefenseStatus() == 0) {
                return true;
            } else {
                return false;
            }
        }).map(AyStructureDisposition::getId).collect(Collectors.toSet());
        return this.removeBatchByIds(set);
    }

    @Override
    public boolean startStructureDisposition(Integer id) {
        //1. 查询布控任务信息
        AyStructureDisposition ayStructureDisposition = this.getById(id);
        if (ayStructureDisposition == null) {
            throw new ServiceException("任务不存在");
        }
        //2.判断布控任务状态
        if (ayStructureDisposition.getStatus() == ControlStatusEnum.NOT_STARTED.getValue() || ayStructureDisposition.getStatus() == ControlStatusEnum.FINISHED.getValue()) {
            ayStructureDisposition.setStatus(ControlStatusEnum.RUNING.getValue());
            ayStructureDisposition.setDefenseStatus(1);
            boolean update = this.updateById(ayStructureDisposition);
            if (update) {
                AyDispositionPlanDto planDto = new AyDispositionPlanDto();
                BeanCopyUtils.copy(ayStructureDisposition, planDto);
                sendRedis(ayStructureDisposition.getDispositionRangeDevice().split(","), planDto);
                return true;
            }
            return false;
        }
        throw new ServiceException("不符合启动条件的布控任务");
    }

    @Override
    public boolean stopStructureDisposition(Integer id) {
        //1. 查询布控任务信息
        AyStructureDisposition ayStructureDisposition = this.getById(id);
        if (ayStructureDisposition == null) {
            throw new ServiceException("任务不存在");
        }
        //2.判断布控任务状态
        if (ayStructureDisposition.getStatus() == ControlStatusEnum.RUNING.getValue()) {
            ayStructureDisposition.setStatus(ControlStatusEnum.FINISHED.getValue());
            ayStructureDisposition.setDefenseStatus(0);
            boolean update = this.updateById(ayStructureDisposition);
            if (update) {
                AyDispositionPlanDto planDto = new AyDispositionPlanDto();
                BeanCopyUtils.copy(ayStructureDisposition, planDto);
                sendRedis(ayStructureDisposition.getDispositionRangeDevice().split(","), planDto);
                return true;
            }
            return false;
        }
        throw new ServiceException("不符合停止条件的布控任务");
    }

    @Override
    public boolean armedAndDisarmed(AyTaskIdDto ayTaskIdDto) {
        List<AyStructureDisposition> ayStructureDispositions = this.listByIds(ayTaskIdDto.getIds());
        AyDispositionPlanDto planDto = new AyDispositionPlanDto();
        ayStructureDispositions.forEach(item -> {
            item.setDefenseStatus(item.getDefenseStatus() == 0 ? 1 : 0);
            //更新redis布防撤防信息
            item.setUpdatedBy(ayTaskIdDto.getUpdatedBy());
            item.setUpdatedId(ayTaskIdDto.getUpdatedId());
            BeanCopyUtils.copy(item, planDto);
            sendRedis(item.getDispositionRangeDevice().split(","), planDto);
        });
        return this.updateBatchById(ayStructureDispositions);
    }

    @Override
    public boolean updateTempVehicleGroup(AyStructureDispositionDto ayStructureDispositionDto) {
        if (null != ayStructureDispositionDto.getTempVehicleGroup() && 0 == ayStructureDispositionDto.getAlarmType()
        ) {
            //查询
            AyStructureDisposition ayStructureDisposition = this.getById(ayStructureDispositionDto.getId());
            if (STRUCTURE_DISPOSITION_VEHICLE_TYPE_GROUP != ayStructureDisposition.getDispositionType()) {
                return false;
            }
            //设置临时输出
            if (ayStructureDisposition.getAlarmType() == 0) {
                ayStructureDisposition.setTempVehicleGroup(ayStructureDispositionDto.getTempVehicleGroup());
                ayStructureDisposition.setTempBeginTime(getTime(ayStructureDispositionDto.getTempBeginTime().toString()));
                ayStructureDisposition.setTempEndTime(getTime(ayStructureDispositionDto.getTempEndTime().toString()));
                //更新数据库
                boolean update = this.updateById(ayStructureDisposition);
                return update;
            }
            return false;
        }
        throw new ServiceException("不符合条件的临时车辆库白名单");

    }

    /**
     * 添加布防计划
     *
     * @param ayStructureDisposition 布控任务
     */
    private AyDispositionPlanDto addAyDispositionPlan(AyStructureDisposition ayStructureDisposition) {
        AyDispositionPlanDto ayDispositionPlanDto = copyByTemplate(ayStructureDisposition);
        //添加布防计划
        systemFeignService.add(JSONObject.toJSONString(ayDispositionPlanDto));
        return ayDispositionPlanDto;
    }

    /**
     * 远程查询模板信息
     *
     * @param ayStructureDisposition 结构化布控任务
     * @return AyPlanTemplateDto
     */
    private AyPlanTemplateDto getPlanTemplate(AyStructureDisposition ayStructureDisposition) {
        ResponseResult result = systemFeignService.id(ayStructureDisposition.getPlanTemplateId());
        String jsonString = JSONObject.toJSONString(result.getData());
        return JSON.parseObject(jsonString, AyPlanTemplateDto.class);
    }

    private AyDispositionPlanDto updateAyDispositionPlan(AyStructureDisposition ayStructureDisposition) {
        //1. 查询模板信息
        AyPlanTemplateDto ayPlanTemplateDto = getPlanTemplate(ayStructureDisposition);
        ResponseResult result = systemFeignService.selectById(ayStructureDisposition.getId());
        String jsonString = JSONObject.toJSONString(result.getData());
        AyDispositionPlanDto ayDispositionPlanDto = JSON.parseObject(jsonString, new TypeReference<AyDispositionPlanDto>() {
        });
        ayDispositionPlanDto.setPlanType(ayPlanTemplateDto.getPlanType());
        ayDispositionPlanDto.setPlanInfoNum(ayPlanTemplateDto.getPlanInfoNum());
        ayDispositionPlanDto.setPlanInfoList(ayPlanTemplateDto.getPlanInfoList());
        systemFeignService.updateDispositionPlan(JSONObject.toJSONString(ayDispositionPlanDto));
        return ayDispositionPlanDto;
    }

    private void sendRedis(String[] str, AyDispositionPlanDto planDto) {
        Arrays.stream(str).forEach(item -> {
            planDto.setDeviceId(item);
            RedisUtil.set(CONTROL_STRUCTURE_CONDITION + item, JSON.toJSONString(planDto));
        });
    }

    /**
     * 模板信息
     */
    private AyDispositionPlanDto copyByTemplate(AyStructureDisposition disposition) {
        //1. 查询模板信息
        AyPlanTemplateDto ayPlanTemplateDto = getPlanTemplate(disposition);
        //2. 封装布防信息
        AyDispositionPlanDto ayDispositionPlanDto = new AyDispositionPlanDto();
        ayDispositionPlanDto.setDispositionId(disposition.getId().toString());
        ayDispositionPlanDto.setDispositionType(1);
        ayDispositionPlanDto.setPlanType(ayPlanTemplateDto.getPlanType());
        ayDispositionPlanDto.setPlanInfoNum(ayPlanTemplateDto.getPlanInfoNum());
        ayDispositionPlanDto.setPlanInfoList(ayPlanTemplateDto.getPlanInfoList());
        return ayDispositionPlanDto;
    }

    private LocalDateTime getTime(String time) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = null;
        try {
            date = dateFormat.parse(time);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        assert date != null;
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        return instant.atZone(zoneId).toLocalDateTime();
    }


}
